<?php
/**
 * @file: Question_votem.php
 * @User: shiwuhao
 * @Date: 16/3/30 14:13
 * @synopsis:
 */

class Question_votem extends CI_Model
{
    // 投票贴 post_type_extend 值
    private $vote_extend = 5;
    // 问答贴 post_type_extend 值
    private $question_extend = 4;
    // 评论倍数
    private $comment_double = 3;
    // 收藏倍数
    private $favorite_double = 1;
    // 投票倍数
    private $vote_double = 1;
    // 问答投票 数据条数 分别
    private $limit = 100;
    // 标签下 缓存key前缀
    private $tag_heat_post_ids = 'tag:heat_post_ids_';
    // 科室下 缓存key前缀
    private $thread_heat_post_ids = 'thread:heat_post_ids_';
    // 全部下 缓存key前缀
    private $thread_tag_heat_post_ids = 'thread:tag:heat_post_ids';

    public function __construct()
    {
        parent::__construct();
        $this->load->model('postm');
    }

    /**
     * 获取热门 问答投票列表
     * @param int $user_id 用户ID
     * @param string $res_name 资源名称  （thread | tag）
     * @param int $res_id 资源ID    (thread_id | tag_id)
     * @param int $page 当前页数
     * @param int $per_page 分页条数
     * @return array
     */
    public function get_heat_ids($res_name = '', $res_id = 0, $page = 1, $per_page = 10, $cache = 1)
    {
        $heat_ids = array();
        $start = ($page - 1) * $per_page;
        $end = $per_page;
        if ($res_name == 'thread') { // 科室
            $key = $this->thread_heat_post_ids . $res_id;
        } elseif ($res_name == 'tag') { // 标签
            $key = $this->tag_heat_post_ids . $res_id;
        } else {
            $key = $this->thread_tag_heat_post_ids;
        }
        if ($this->mc->is_supported() && $cache) {
            $heat_ids = $this->mc->get($key);
        }
        // 不存在 查库
        if (!$heat_ids) {
            $question_supplement = $vote_supplement = array();
            $question_filter = array('post_type_extend' => $this->question_extend, 'status' => 1, 'add_time >=' => date('Y-m-d H:i:s', strtotime('-1 day')));
            $vote_filter = array('post_type_extend' => $this->vote_extend, 'status' => 1, 'add_time >=' => date('Y-m-d H:i:s', strtotime('-1 day')));
            // 问答
            if ($res_name == 'thread') { // 科室
                $this->db->like('thread_ids', ',' . $res_id);
            } elseif ($res_name == 'tag') { // 标签
                $this->db->like('tag_ids', ',' . $res_id);
            }
            $question_results_ = $this->db->where($question_filter)->order_by('heat', 'DESC')->limit($this->limit)->get('ml_heat')->result_array();

            // 特殊需求处理
            $spe_flag = 0;
            if (!empty($question_results_)) {
                if (count($question_results_) > 10) {
                    $spe_flag = 1;
                    $heat_question_spe = array_slice($question_results_, 0, 10);
                    $question_results = array_slice($question_results_, 10);
                } else {
                    $spe_flag = 2;
                    $heat_question_spe = $question_results_;
                    $question_results = array();
                }
            }

            // 投票
            if ($res_name == 'thread') { // 科室
                $this->db->like('thread_ids', ',' . $res_id);
            } elseif ($res_name == 'tag') { // 标签
                $this->db->like('tag_ids', ',' . $res_id);
            }
            $vote_results = $this->db->where($vote_filter)->order_by('heat', 'DESC')->limit($this->limit)->get('ml_heat')->result_array();

            // 24小时热度排序
            $heat_one_day_merge = array();
            if (!empty($question_results)) {
                $heat_one_day_merge = array_merge($question_results, $vote_results);
            }

            // 热度数据排序
            $heat_one_day = $this->multisort_by_field($heat_one_day_merge, 'SORT_DESC', 'heat');

            if ($spe_flag == 1) {
                $question_total = count($question_results) + 10;
            } else {
                $question_total = count($question_results_);
            }
            $vote_total = count($vote_results);

            // 问答不足100 补充
            if ($question_total < $this->limit) {
                if ($res_name == 'thread') { // 科室
                    $this->db->like('thread_ids', ',' . $res_id);
                } elseif ($res_name == 'tag') { // 标签
                    $this->db->like('tag_ids', ',' . $res_id);
                }

                unset($question_filter['add_time >=']);
                $_limit = $this->limit - $question_total;
                $not_in_ids = array(-1);
                if (!empty($question_results)) {
                    $not_in_ids = array_column($question_results, 'post_id');
                }
                $question_supplement = $this->db->where($question_filter)->where_not_in('post_id', $not_in_ids)->group_by('post_id')->order_by('heat', 'DESC')->limit($_limit)->get('ml_heat')->result_array();
            }
            // 投票不足100 补充
            if ($vote_total < $this->limit) {
                if ($res_name == 'thread') { // 科室
                    $this->db->like('thread_ids', ',' . $res_id);
                } elseif ($res_name == 'tag') { // 标签
                    $this->db->like('tag_ids', ',' . $res_id);
                }

                unset($vote_filter['add_time >=']);
                $_limit = $this->limit - $vote_total;
                $not_in_ids = array_column($vote_results, 'post_id');
                $not_in_ids = $not_in_ids ? $not_in_ids : array(-1);
                $vote_supplement = $this->db->where($vote_filter)->where_not_in('post_id', $not_in_ids)->group_by('post_id')->order_by('heat', 'DESC')->limit($_limit)->get('ml_heat')->result_array();
            }
            // 不足100合并数据
            $heat_list_merge = array_merge($question_supplement, $vote_supplement);

            // 热度数据排序
            $heat_list_supplement = $this->multisort_by_field($heat_list_merge, 'SORT_DESC', 'heat');

            // 数据整体合并
            if (!empty($heat_question_spe)) {
                $heat_list = array_merge($heat_question_spe, $heat_one_day, $heat_list_supplement);
            } else {
                $heat_list = array_merge($heat_one_day, $heat_list_supplement);
            }

            $heat_ids = array();
            if (!empty($heat_list)) {
                $heat_ids = array_column($heat_list, 'post_id');
            }

            // 加入缓存
            if ($this->mc->is_supported()) {
                $this->mc->save($key, $heat_ids, 60*5);
            }
        }

        if (!empty($heat_ids)) {
            $heat_ids = array_slice($heat_ids, $start, $end);
        }
        return $heat_ids;
    }

    /**
     * 按热度排序
     * @direction (SORT_ASC  || SORT_DESC)
     * @field 用来排序字段
     * @return array
     */
    function multisort_by_field($heat_list, $direction, $field)
    {
        if (!empty($heat_list)) {
            foreach ($heat_list AS $uniqid => $row) {
                foreach ($row AS $key => $value) {
                    if ($key == $field) {
                        $arrSort[$key][$uniqid] = $value;
                    }
                }
            }
        }
        if ($direction) {
            if (!empty($arrSort[$field])) {
                array_multisort($arrSort[$field], constant($direction), $heat_list);
            }
        }
        return $heat_list;
    }

    /**
     * 过滤屏蔽贴及屏蔽用户
     * @return array
     */
    function handle_heat($heat_ids, $hate_ids = array(), $hate_users = array())
    {
        $heat_post_ids = array();
        // 过滤屏蔽帖子
        if (!empty($heat_ids)) {
            foreach ($heat_ids as $k => $v) {
                if (!in_array($v, $hate_ids)) {
                    $heat_post_ids[] = $v;
                }
            }
        }
        // 过滤屏蔽用户
        return $heat_post_ids;
    }

    /**
     * 获取热度问答t投票列表
     * @return array
     */
    public function get_heat_list($user_id = 0, $res_name = '', $res_id = 0, $page = 1, $per_page = 10)
    {
        $list = array();
        $heat_ids = self::get_heat_ids($res_name, $res_id, $page, $per_page);
        // 过滤屏蔽贴及屏蔽用户
        $this->load->model('hatem');
        $hate_info = $this->hatem->get_hatelist($user_id);
        $hate_ids = $hate_info['hate_ids'] ? $hate_info['hate_ids'] : array();
        $hate_users = $hate_info['hate_user'] ? $hate_info['hate_user'] : array();
        $heat_handle_hate = $this->handle_heat($heat_ids, $hate_ids, $hate_users);
        if ($heat_handle_hate) {
            foreach ($heat_handle_hate as $v) {
                $info = $this->postm->get_one_post_info($v, 1, 1);
                if ($info) $list[] = $info;
            }
        }
        return $list;
    }

    /**
     * 更新热度表
     */
    public function update_heat($hours)
    {
        if (!$hours) return false;
        $start_time = strtotime("-{$hours} hours");
        $post_ids = self::get_heat_post_ids($start_time);

        foreach ($post_ids as $v) {

            // 科室ID
            $thread_ids = $tag_ids = '';
            $post_type = $this->postm->get_post_type_ids($v);
            if (isset($post_type['thread_ids']) && $post_type['thread_ids']) {
                $thread_ids = ',' . join(',', $post_type['thread_ids']);
            }

            // 标签ID
            if (isset($post_type['tag_ids']) && $post_type['tag_ids']) {
                $tag_ids = ',' . join(',', $post_type['tag_ids']);
            }

            // 数量
            $filter = array('addtime >=' => $start_time, 'post_id' => $v);
            $comment_total = $this->db->where($filter)->count_all_results('ml_comment');
            $favorite_total = $this->db->where($filter)->count_all_results('ml_favorite');
            $vote_total = $this->db->where($filter)->count_all_results('ml_vote_relation');

            // 计算热度
            $heat = 0;
            $info = $this->db->select('post_type_extend')->where('id', $v)->from('ml_post')->get()->row_array();
            if ($info['post_type_extend'] == $this->vote_extend) { // 问答
                $heat = $comment_total * $this->comment_double + $favorite_total * $this->favorite_double + $vote_total * $this->vote_double;
            } elseif ($info['post_type_extend'] == $this->question_extend) { // 投票
                $heat = $comment_total * $this->comment_double + $favorite_total * $this->favorite_double;
            } else {
                w_log('error:Invalid data type');
            }

            $time = date('Y-m-d H:i:s');

            $data = array(
                'post_id' => $v,
                'thread_ids' => $thread_ids,
                'tag_ids' => $tag_ids,
                'post_type_extend' => $info['post_type_extend'],
                'add_time' => $time,
                'heat' => $heat
            );

            $filter = array('add_time >=' => date('Y-m-d H:i:s', strtotime('-1 days')), 'post_id' => $v);
            $heat_info = $this->db->where($filter)->get('ml_heat')->row_array();
            if ($heat_info) {
                $data['update_time'] = $time;
                $this->db->update('ml_heat', $data, array('id' => $heat_info['id']));
            } else {
                $this->db->insert('ml_heat', $data);
            }
        }

        return true;
    }

    /**
     * 获取一定时间之内的投票贴 ids
     */
    public function get_heat_post_ids($start_time)
    {
        if (!$start_time) return array();
        $filter = array('a.addtime >=' => $start_time, 'b.is_show' => 1);
        $post_type_extend = array($this->vote_extend, $this->question_extend);

        // 时间范围内的评论帖子ID
        $comment_post_ids = $this->db->select('a.post_id')
            ->distinct()
            ->from('ml_comment as a')
            ->join('ml_post as b', 'a.post_id=b.id', 'left')
            ->where($filter)
            ->where_in('b.post_type_extend', $post_type_extend)
            ->order_by('a.id', 'DESC')
            ->get()
            ->result_array();

        // 时间范围内的收藏贴ID
        $favorite_post_ids = $this->db->select('a.post_id')
            ->distinct()
            ->from('ml_favorite as a')
            ->join('ml_post as b', 'a.post_id=b.id', 'left')
            ->where($filter)
            ->where_in('b.post_type_extend', $post_type_extend)
            ->order_by('a.id', 'DESC')
            ->get()
            ->result_array();

        // 时间范围内的投票贴ID
        $vote_post_ids = $this->db->select('a.post_id')
            ->distinct()
            ->from('ml_vote_relation as a')
            ->join('ml_post as b', 'a.post_id=b.id', 'left')
            ->where($filter)
            ->where_in('b.post_type_extend', $post_type_extend)
            ->order_by('a.id', 'DESC')
            ->get()
            ->result_array();

        $favorite_post_ids = array_column($favorite_post_ids, 'post_id');
        $comment_post_ids = array_column($comment_post_ids, 'post_id');
        $vote_post_ids = array_column($vote_post_ids, 'post_id');
        $post_ids = array_unique(array_merge($comment_post_ids, $favorite_post_ids, $vote_post_ids));
        return $post_ids;
    }

    /**
     * 获取用户选择的投票选项
     * @param $user_id
     * @param $post_id
     */
    public function get_select_vote_option_name($user_id, $post_id)
    {
        $result = $this->db->select('b.option')
            ->from('ml_vote_relation as a')
            ->join('ml_vote_option as b', 'a.option_id=b.id', 'left')
            ->where(array('a.clicker_id' => $user_id, 'a.post_id' => $post_id))
            ->get()
            ->row_array();
        if ($result) return $result['option'];
        return '';
    }
}